﻿using AutoMapper;
using Microsoft.AspNetCore.Http;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using System.Diagnostics;
using TrackSystem.Contracts;
using TrackSystem.Entities.Dtos.Channel;
using TrackSystem.Entities.Extensions;
using TrackSystem.Entities.Models;
using TrackSystem.Entities.RequestFeatures;
using TrackSystem.EntityFramework.Repositories.Extensions;

namespace TrackSystem.EntityFramework.Repositories
{
    public class ChannelRepository : Repositories<ChannelTable, int>, IChannelRepository
    {
        private readonly IMapper _mapper;

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="dbContent">数据库</param>
        /// <param name="mapper">映射接口</param>
        public ChannelRepository(TkDBContent dbContent, IMapper mapper) : base(dbContent)
        {
            _mapper = mapper;
        }

        /// <summary>
        /// 获取所有通道信息,包括传感器信息
        /// </summary>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<IEnumerable<ChannelTable>> GetAllListWithSensorAsync()
        {
            return await Table.Include(c => c.Sensors).ToListAsync();
        }

        /// <summary>
        /// 获取分页通道数据
        /// </summary>
        /// <param name="parameter"></param>
        /// <returns></returns>
        public PagedList<ChannelTable> GetPagedChannels(RequestParameter parameter)
        {
            return Table.OrderByQuery(parameter.QueryString)
                .Include(channel => channel.Sensors)
                .ToPagedList(parameter.PageNumber, parameter.PageSize);
        }

        /// <summary>
        /// 添加通道
        /// </summary>
        /// <param name="channel"></param>
        /// <returns></returns>
        public async Task<ApiResult<ChannelDto>> InsertChannelAsync(ChannelDto channel)
        {
            var entity = _mapper.Map<ChannelTable>(channel);
            var count = await Table.CountAsync(x => x.Name == entity.Name);
            if (count > 0)
            {
                return ApiResult<ChannelDto>.Fail($"通道名称{entity.Name}已存在，请更换通道名称", 201);
            }

            if (entity.PortCategory != PortCategory.SRIAL)
            {
                if (FormatChecker.IsValidIP(entity.Ip) == false)
                {
                    return ApiResult<ChannelDto>.Fail($"通道远程IP地址({entity.Ip})不合法", 202);
                }
                if (entity.Port is <= 0 or > 65535)
                {
                    return ApiResult<ChannelDto>.Fail($"通道远程端口号({entity.Port})不合法", 203);
                }

                // 检查远程IP和端口号是否已存在，排除串口通信方式
                count = await Table.CountAsync(x =>
                    x.Ip == entity.Ip &&
                    x.Port == entity.Port &&
                    x.PortCategory != PortCategory.SRIAL);
                if (count > 0)
                {
                    return ApiResult<ChannelDto>.Fail($"通道远程IP和端口号({entity.Ip}:{entity.Port})已存在，请更换通道远程IP和端口号", 204);
                }

                count = await Table.CountAsync(x =>
                    x.localIp == entity.Ip &&
                    x.localPort == entity.Port &&
                    x.PortCategory != PortCategory.SRIAL);
                if (count > 0)
                {
                    return ApiResult<ChannelDto>.Fail($"通道远程IP和端口号({entity.Ip}:{entity.Port})已存在，请更换通道远程IP和端口号", 204);
                }

                if (entity.PortCategory == PortCategory.UDP)
                {
                    if (FormatChecker.IsValidIP(entity.localIp) == false)
                    {
                        return ApiResult<ChannelDto>.Fail($"通道本地IP地址({entity.localIp})不合法", 204);
                    }
                    if (entity.localPort <= 0 || entity.localPort > 65535)
                    {
                        return ApiResult<ChannelDto>.Fail($"通道本地端口号({entity.localPort})不合法", 205);
                    }

                    // 检查远程IP和端口号是否已存在，排除串口通信方式
                    count = await Table.CountAsync(x =>
                        x.Ip == entity.localIp &&
                        x.Port == entity.localPort &&
                        x.PortCategory != PortCategory.SRIAL);
                    if (count > 0)
                    {
                        return ApiResult<ChannelDto>.Fail($"通道本地IP和端口号({entity.localIp}:{entity.localPort})已存在，请更换通道远程IP和端口号", 204);
                    }

                    count = await Table.CountAsync(x =>
                        x.localIp == entity.localIp &&
                        x.localPort == entity.localPort &&
                        x.PortCategory != PortCategory.SRIAL);
                    if (count > 0)
                    {
                        return ApiResult<ChannelDto>.Fail($"通道本地IP和端口号({entity.localIp}:{entity.localPort})已存在，请更换通道远程IP和端口号", 204);
                    }
                }
            }
            else
            {
                if (!FormatChecker.IsValidSerialParams(entity.SerialParams))
                {
                    return ApiResult<ChannelDto>.Fail($"串口参数({entity.SerialParams})不合法,例如N-8-1格式", 205);
                }

                count = await Table.CountAsync(x =>
                    x.COMn == entity.COMn && x.PortCategory == PortCategory.SRIAL);
                if (count > 0)
                {
                    return ApiResult<ChannelDto>.Fail($"串口通道名称{entity.COMn}已存在，请更换串口通道名称", 206);
                }
            }

            if (entity.Interval < 50)
            {
                return ApiResult<ChannelDto>.Fail($"通道扫描时间不能低于50", 205);
            }

            var channelTable = await InsertAsync(entity);
            return ApiResult<ChannelDto>.Ok(_mapper.Map<ChannelDto>(channelTable));
        }

        /// <summary>
        /// 更新通道信息
        /// </summary>
        /// <param name="channel"></param>
        /// <returns></returns>
        public async Task<ApiResult<ChannelDto>> UpdateChannelAsync(ChannelDto channel)
        {
            //STEP 1  检查通道是否存在
            var CurChn = Table.AsNoTracking().Where(c => c.Id == channel.Id).Include(c => c.Sensors).FirstOrDefault();
            if (CurChn == null)
            {
                string errorMessage = "端口不存在";
                return ApiResult<ChannelDto>.Fail(errorMessage, StatusCodes.Status204NoContent);
            }

            //STEP 2  检查通道是否被传感器使用
            if (CurChn.Protocol != channel.Protocol && CurChn.Sensors != null && CurChn.Sensors.Count > 0)
            {
                string errorMessage = $"通道{channel.Name}的通道信息已被传感器使用，无法修改";
                return ApiResult<ChannelDto>.Fail(errorMessage, StatusCodes.Status204NoContent);
            }

            //STEP 3  端口名称校验
            var HasChannel = Table.Count(a => a.Name.Trim() == channel.Name.Trim() && a.Id != channel.Id);
            if (HasChannel > 0)
            {
                string errorMessage = $"存在同名的通道({channel.Name})";
                return ApiResult<ChannelDto>.Fail(errorMessage, StatusCodes.Status300MultipleChoices);
            }

            //STEP 4  IP地址和端口校验
            if (channel.PortCategory != PortCategory.SRIAL)
            {
                HasChannel = Table.Count(a => a.Ip == channel.Ip && a.Port == channel.Port && a.Id != channel.Id);
                if (HasChannel > 0)
                {
                    string errorMessage = $"存在相同远程IP地址和端口号的通道({channel.Ip}:{channel.Port})";
                    return ApiResult<ChannelDto>.Fail(errorMessage, StatusCodes.Status300MultipleChoices);
                }
                if (channel.PortCategory == PortCategory.UDP)
                {
                    HasChannel = Table.Count(a =>
                    a.localIp == channel.localIp &&
                    a.localPort == channel.localPort &&
                    a.Id != channel.Id);
                    if (HasChannel > 0)
                    {
                        string errorMessage = $"存在相同本地IP地址和端口号的通道({channel.localIp}:{channel.localPort})";
                        return ApiResult<ChannelDto>.Fail(errorMessage, StatusCodes.Status300MultipleChoices);
                    }
                }
            }
            else
            {
                var hasCom = Table.Count(a => a.COMn == channel.COMn && a.Id != channel.Id);
                if (hasCom > 0)
                {
                    string errorMessage = $"存在相同的串口地址({channel.COMn})";
                    return ApiResult<ChannelDto>.Fail(errorMessage, StatusCodes.Status300MultipleChoices);
                }
            }

            if (channel.Interval < 50)
            {
                return ApiResult<ChannelDto>.Fail($"通道扫描时间不能低于50", StatusCodes.Status406NotAcceptable);
            }

            var cur = _mapper.Map<ChannelTable>(channel);
            var result = await UpdateAsync(cur);

            return ApiResult<ChannelDto>.Ok(channel);

        }

        public async Task<ApiResult<ChannelDto>> DeleteChannelAsync(int id)
        {
            var channel = await SingleAsync(a => a.Id == id);

            var sensors = _dbContext.Sensors.Count(a => a.channelID == id);
            if (sensors > 0)
            {
                string errorMessage = $"通道ID为{id}的通道信息已被传感器使用，无法删除";
                return ApiResult<ChannelDto>.Fail(errorMessage, StatusCodes.Status204NoContent);
            }

            await DeleteAsync(channel);
            return ApiResult<ChannelDto>.Ok($"通道ID为{id}的通道信息删除成功");
        }
    }
}
